// Copyright 2018 The PDFium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CORE_FPDFAPI_PARSER_CPDF_CROSS_REF_TABLE_H_
#define CORE_FPDFAPI_PARSER_CPDF_CROSS_REF_TABLE_H_

#include <stdint.h>

#include <map>
#include <memory>

#include "core/fxcrt/fx_types.h"
#include "core/fxcrt/retain_ptr.h"

class CPDF_Dictionary;

class CPDF_CrossRefTable {
 public:
  // See ISO 32000-1:2008 table 18.
  enum class ObjectType : uint8_t {
    kFree = 0,
    kNormal = 1,
    kCompressed = 2,
  };

  struct ObjectInfo {
    ObjectType type = ObjectType::kFree;
    bool is_object_stream_flag = false;
    uint16_t gennum = 0;
    // If `type` is `ObjectType::kCompressed`, `archive` should be used.
    // If `type` is `ObjectType::kNormal`, `pos` should be used.
    // In other cases, it is unused.
    union {
      FX_FILESIZE pos = 0;
      struct {
        uint32_t obj_num;
        uint32_t obj_index;
      } archive;
    };
  };

  // Merge cross reference tables.  Apply top on current.
  static std::unique_ptr<CPDF_CrossRefTable> MergeUp(
      std::unique_ptr<CPDF_CrossRefTable> current,
      std::unique_ptr<CPDF_CrossRefTable> top);

  CPDF_CrossRefTable();
  CPDF_CrossRefTable(RetainPtr<CPDF_Dictionary> trailer,
                     uint32_t trailer_object_number);
  ~CPDF_CrossRefTable();

  void AddCompressed(uint32_t obj_num,
                     uint32_t archive_obj_num,
                     uint32_t archive_obj_index);
  void AddNormal(uint32_t obj_num,
                 uint16_t gen_num,
                 bool is_object_stream,
                 FX_FILESIZE pos);
  void SetFree(uint32_t obj_num, uint16_t gen_num);

  void SetTrailer(RetainPtr<CPDF_Dictionary> trailer,
                  uint32_t trailer_object_number);
  uint32_t trailer_object_number() const { return trailer_object_number_; }
  const CPDF_Dictionary* trailer() const { return trailer_.Get(); }
  CPDF_Dictionary* GetMutableTrailerForTesting() { return trailer_.Get(); }

  const ObjectInfo* GetObjectInfo(uint32_t obj_num) const;

  const std::map<uint32_t, ObjectInfo>& objects_info() const {
    return objects_info_;
  }

  void Update(std::unique_ptr<CPDF_CrossRefTable> new_cross_ref);

  // Objects with object number >= `size` will be removed.
  void SetObjectMapSize(uint32_t size);

 private:
  void UpdateInfo(std::map<uint32_t, ObjectInfo> new_objects_info);
  void UpdateTrailer(RetainPtr<CPDF_Dictionary> new_trailer);

  RetainPtr<CPDF_Dictionary> trailer_;
  // `trailer_` can be the dictionary part of a XRef stream object. Since it is
  // inline, it has no object number. Store the stream's object number, or 0 if
  // there is none.
  uint32_t trailer_object_number_ = 0;
  std::map<uint32_t, ObjectInfo> objects_info_;
};

#endif  // CORE_FPDFAPI_PARSER_CPDF_CROSS_REF_TABLE_H_



 

以下是 `CPDF_CrossRefTable` 类中提供的接口功能：

### 数据结构和枚举
1. **enum class ObjectType**: 表示对象的类型，有三种可能的值：
   - `kFree`: 表示对象是空闲的。
   - `kNormal`: 表示对象是普通的。
   - `kCompressed`: 表示对象是压缩的。

2. **struct ObjectInfo**: 保存对象信息的数据结构。包含以下字段：
   - `type`: 对象类型，使用 `ObjectType` 枚举。
   - `is_object_stream_flag`: 布尔标记，表示是否是对象流。
   - `gennum`: 对象的生成号。
   - `pos` 或 `archive`: 根据对象类型保存对象的位置信息或压缩信息。

### 静态方法
3. **MergeUp(std::unique_ptr<CPDF_CrossRefTable> current, std::unique_ptr<CPDF_CrossRefTable> top)**: 合并交叉引用表，将新的交叉引用表合并到当前的表中。

### 构造函数和析构函数
4. **CPDF_CrossRefTable()**: 默认构造函数。
5. **CPDF_CrossRefTable(RetainPtr<CPDF_Dictionary> trailer, uint32_t trailer_object_number)**: 带参数的构造函数，用于初始化尾随和尾随对象编号。
6. **~CPDF_CrossRefTable()**: 析构函数，负责清理资源。

### 公共方法
7. **AddCompressed(uint32_t obj_num, uint32_t archive_obj_num, uint32_t archive_obj_index)**: 添加压缩对象的信息。
8. **AddNormal(uint32_t obj_num, uint16_t gen_num, bool is_object_stream, FX_FILESIZE pos)**: 添加普通对象的信息。
9. **SetFree(uint32_t obj_num, uint16_t gen_num)**: 设置对象为空闲状态。
10. **SetTrailer(RetainPtr<CPDF_Dictionary> trailer, uint32_t trailer_object_number)**: 设置交叉引用表的尾随信息。
11. **trailer_object_number()**: 返回尾随对象编号。
12. **trailer()**: 返回尾随字典的常量指针。
13. **GetMutableTrailerForTesting()**: 返回可变的尾随字典指针，用于测试。
14. **GetObjectInfo(uint32_t obj_num) const**: 返回给定对象编号的对象信息。
15. **objects_info() const**: 返回所有对象信息的映射。
16. **Update(std::unique_ptr<CPDF_CrossRefTable> new_cross_ref)**: 使用新的交叉引用表更新当前表。
17. **SetObjectMapSize(uint32_t size)**: 移除对象编号大于或等于 `size` 的对象。

### 私有方法
18. **UpdateInfo(std::map<uint32_t, ObjectInfo> new_objects_info)**: 更新对象信息。
19. **UpdateTrailer(RetainPtr<CPDF_Dictionary> new_trailer)**: 更新尾随字典。

这些接口共同提供了对 PDF 文档中的交叉引用表的创建、更新和查询机制，用于管理 PDF 对象的解析和状态跟踪。
*/